package licode.unisop.auth.adapter.web;

import licode.unisop.auth.application.executor.SessionExecutor;
import licode.unisop.auth.client.info.UserIdFindIn;
import licode.unisop.client.api.auth.SopResourceQuery;
import licode.unisop.client.api.auth.SopUserAuthQuery;
import licode.unisop.client.info.*;
import licode.unisop.client.inter.HasAuthority;
import licode.unisop.client.utils.PlatformCheck;
import licode.unisop.client.utils.SopRequestParse;
import licode.unisop.client.vo.*;
import licode.unisop.oidc.auth.modal.SessionDetail;
import licode.unisop.types.AuthConst;
import licode.unisop.unilite.result.UniResult;
import licode.unisop.unilite.result.UniReturnResult;
import licode.unisop.unilite.utils.TryMethodCall;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * 定义认证信息获取接口
 *
 * @author WR
 */
@RestController
@UniReturnResult
@RequestMapping("/uni-auth/v1/token")
public class AuthTokenController {
    @Resource
    private HttpServletRequest request;

    @Resource
    private PlatformCheck platformCheck;

    @Resource
    private SopUserAuthQuery queryAuth;

    @Resource
    private SopResourceQuery resourceQuery;

    @Resource
    private SessionExecutor sessionExecutor;

    private SopTokenInfo calcAuthToken() {
        return SopTokenInfo.builder()
                .realmId(SopRequestParse.getValue(request, AuthConst.REALM_ID))
                .token(SopRequestParse.getValue(request, AuthConst.ACCESS_TOKEN))
                .platformId(SopRequestParse.getValue(request, AuthConst.PLATFORM_TOKEN))
                .build();
    }

    /**
     * 返回指定token的用户资源
     *
     * @return token的详情
     */
    @PostMapping("/user-assets")
    public UniResult<SopUserAssets> getUserRes() {
        return TryMethodCall.exec(null, () -> {
            platformCheck.checkPlatform(request);
            SopTokenInfo tokenInfo = calcAuthToken();
            return resourceQuery.getUserAssets(tokenInfo);
        });
    }

    @PostMapping("/auth-brief")
    public UniResult<SopAuthBrief> getAuthBrief() {
        return TryMethodCall.exec(null,
                () -> {
                    platformCheck.checkPlatform(request);
                    return queryAuth.getAuthBrief(calcAuthToken());
                });
    }

    @PostMapping("/auth-user-info")
    public UniResult<SopAuthUser> getAuthUserInfo() {
        return TryMethodCall.exec(null,
                () -> {
                    platformCheck.checkPlatform(request);
                    return queryAuth.getAuthUserInfo(calcAuthToken());
                });
    }

    /**
     * 返回指定token的用户信息
     *
     * @return token的详情
     */
    @PostMapping("/user-info")
    public UniResult<SopUserBrief> getUserInfo() {
        return TryMethodCall.exec(null,
                () -> {
                    platformCheck.checkPlatform(request);
                    return queryAuth.getUserInfo(calcAuthToken());
                });
    }

    /**
     * 返回指定token的用户和凭证信息
     *
     * @return token的详情
     */
    @PostMapping("/credential")
    public UniResult<SopCredential> getCredential() {
        return TryMethodCall.exec(null,
                () -> {
                    platformCheck.checkPlatform(request);
                    return queryAuth.getCredential(calcAuthToken());
                });
    }

    /**
     * 判断登录token是否有效
     *
     * @return 如果指定token有效返回true；否则返回false
     */
    @PostMapping("/valid")
    public UniResult<Boolean> tokenValid() {
        return TryMethodCall.exec(false,
                () -> {
                    platformCheck.checkPlatform(request);
                    return queryAuth.tokenValid(calcAuthToken());
                });
    }

    @PostMapping("/auth-user-assets")
    public UniResult<Map<String, Object>> getAuthUserAssets() {
        return TryMethodCall.exec(null,
                () -> {
                    platformCheck.checkPlatform(request);
                    return queryAuth.getUserAssets(calcAuthToken());
                });
    }

    @PostMapping("/info")
    public UniResult<SopAuthBrief> getTokenInfo() {
        return TryMethodCall.exec(null, () -> {
            platformCheck.checkPlatform(request);
            SopCredential cred = queryAuth.getCredential(calcAuthToken());
            if (null != cred) {
                return SopAuthBrief.builder()
                        .realmId(cred.getBrief().getRealmId())
                        .userId(cred.getBrief().getUserId())
                        .userType(cred.getBrief().getUserType())
                        .clientId(cred.getBrief().getClientId())
                        .platformId(cred.getBrief().getPlatformId())
                        .tenantId(cred.getBrief().getTenantId())
                        .terminalId(cred.getBrief().getTerminalId())
                        .build();
            } else {
                return null;
            }
        });
    }

    @PostMapping("/session/info")
    public UniResult<SessionDetail> getSessionInfo() {
        return TryMethodCall.exec(null, () -> {
            platformCheck.checkPlatform(request);
            String token = SopRequestParse.getValue(request, AuthConst.ACCESS_TOKEN);
            return sessionExecutor.getSessionInfo(token);
        });
    }

    @PostMapping("/session/info/by-user")
    @HasAuthority(roles = AuthConst.SYSTEM_ADMIN)
    public UniResult<SessionDetail> getSessionInfoByUser(@RequestBody UserIdFindIn infoId) {
        return TryMethodCall.exec(null, () -> {
            platformCheck.checkPlatform(request);
            return sessionExecutor.getSessionInfoByUser(infoId);
        });
    }

    /**
     * 判断登录token是否拥有指定的地址权限
     *
     * @param url 地址（支持ant匹配）
     * @return 如果拥有指定地址权限返回0；否则没有登录返回1;其它匹配失败
     */
    @PostMapping("/match-url")
    public UniResult<SopUrlMatch> matchUrl(@RequestParam("url") String url) {
        return TryMethodCall.exec(SopUrlMatch.noMatch(false),
                () -> resourceQuery.matchUrl(SopUrlInfo.builder()
                        .info(calcAuthToken())
                        .url(url)
                        .build()));
    }

    @PostMapping("/sso-match-url")
    public UniResult<SopUrlMatch> ssoMatchUrl(@RequestParam("url") String url) {
        return TryMethodCall.exec(SopUrlMatch.noMatch(false),
                () -> resourceQuery.matchUrl(SopUrlInfo.builder()
                        .info(calcAuthToken())
                        .url(url)
                        .build()));
    }

    /**
     * 判断登录token是否拥有指定的角色
     *
     * @param info 角色码
     * @return 如果拥有指定角色返回true；否则返回false
     */
    @PostMapping("/has-role")
    public UniResult<Integer> hasRole(@RequestBody SiRoleAction info) {
        return TryMethodCall.exec(-1,
                () -> resourceQuery.hasRole(SopRoleInfo.builder()
                        .info(calcAuthToken())
                        .action(info)
                        .build()).getState());
    }

    /**
     * 判断登录token是否拥有指定的权限
     *
     * @param info 权限码
     * @return 如果拥有指定权限返回true；否则返回false
     */
    @PostMapping("/has-permit")
    public UniResult<Integer> hasPermit(@RequestBody SiPermitAction info) {
        return TryMethodCall.exec(-1,
                () -> resourceQuery.hasPermit(SopPermitInfo.builder()
                        .info(calcAuthToken())
                        .action(info)
                        .build()).getState());
    }

    @PostMapping("/has-authority")
    public UniResult<Integer> hasAuthority(@RequestBody SiAuthorityAction info) {
        return TryMethodCall.exec(-1,
                () -> resourceQuery.hasAuthority(SopAuthorityIn.builder()
                        .info(calcAuthToken())
                        .action(info)
                        .build()).getState());
    }
}
